home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 332 / hcc / g2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-08-26  |  12.1 KB  |  646 lines

  1. /* Copyright (c) 1988 by Sozobon, Limited.  Author: Johann Ruegg
  2.  *
  3.  * Permission is granted to anyone to use this software for any purpose
  4.  * on any computer system, and to redistribute it freely, with the
  5.  * following restrictions:
  6.  * 1) No charge may be made other than reasonable charges for reproduction.
  7.  * 2) Modified versions must be clearly marked as such.
  8.  * 3) The authors are not responsible for any harmful consequences
  9.  *    of using this software, even if they result from defects in it.
  10.  *
  11.  *    g2.c
  12.  *
  13.  *    Generate code for binary nodes.
  14.  */
  15.  
  16. #include <stdio.h>
  17. #include "param.h"
  18. #include "nodes.h"
  19. #include "flags.h"
  20. #include "bstok.h"
  21. #include "gen.h"
  22. #include "ops.h"
  23.  
  24. #define FAIL    0
  25. #define OKAY    1
  26.  
  27. extern int cookflags[];
  28.  
  29. #define isimmed(np)    ((np)->g_flags & IMMEDID)
  30. #define isareg(np)    ((np)->g_token == REGVAR && (np)->g_rno >= AREG)
  31.  
  32. struct bop {
  33.     char *s_op, *u_op;
  34.     int opflags;
  35. } bops[] = {
  36.     {"muls",    "mulu",    EOPD |ASSOC},
  37.     {"divs",    "divu",    EOPD},
  38.     {"divs",    "divu", EOPD},
  39.     {"and",        "and",    EOPD|DOPE|IOPE |ASSOC},
  40.     {"or",        "or",    EOPD|DOPE|IOPE |ASSOC},
  41.     {"eor",        "eor",    DOPE|IOPE |ASSOC},
  42.     {"add",        "add",    EOPD|DOPE|EOPA|IOPE|AOPA|AOPD |ASSOC},
  43.     {"sub",        "sub",    EOPD|DOPE|EOPA|IOPE|AOPA|AOPD},
  44.     {"asl",        "lsl",    DOPD|QOPD|ONEOPM},
  45.     {"asr",        "lsr",    DOPD|QOPD|ONEOPM},
  46. };
  47.  
  48. char *tstnm[] = {
  49.     "lt",        /* < */
  50.     "gt",        /* > */
  51.     "le",        /* <= */
  52.     "ge",        /* >= */
  53.     "eq",        /* == */
  54.     "ne",        /* != */
  55. };
  56.  
  57. int tstx[] = {
  58.     B_LT, B_GT, B_LE, B_GE, B_EQ, B_NE
  59. };
  60.  
  61. char *utstnm[] = {
  62.     "cs",        /* < */
  63.     "hi",        /* > */
  64.     "ls",        /* <= */
  65.     "cc",        /* >= */
  66.     "eq",        /* == */
  67.     "ne",        /* != */
  68. };
  69.  
  70. int utstx[] = {
  71.     B_ULT, B_UGT, B_ULE, B_UGE, B_EQ, B_NE
  72. };
  73.  
  74. b_eval(np, cookie)
  75. register NODEP np;
  76. {
  77.     NODEP lp = np->n_left, rp = np->n_right;
  78.     NODEP tp;
  79.     int lcook = FORADR, rcook = FORADR;
  80.  
  81.     switch (np->g_token) {        /* special cookies */
  82.     case DOUBLE '&':
  83.     case DOUBLE '|':
  84.         lcook = rcook = FORCC;
  85.         break;
  86.     case '?':
  87.         lcook = FORCC;
  88.         break;
  89.     case '(':
  90.         rcook = FORPUSH;
  91.         break;
  92.     case ',':
  93.         if (np->g_offs)    /* function args */
  94.             lcook = rcook = FORPUSH;
  95.         else {
  96.             lcook = FORSIDE;
  97.             rcook = cookie;
  98.         }
  99.         break;
  100.     case '=':
  101.         rcook = FORIMA;
  102.         break;
  103.     case '+':
  104.     case '-':
  105.         tp = rp;
  106.         while (tp->g_token == TCONV && tp->g_ty != ET_F)
  107.             tp = tp->n_left;
  108.         if (tp->g_token == ICON)
  109.             lcook = FORIMA;
  110.         break;        
  111.     }
  112.  
  113.     if (np->g_type == EV_LR) {
  114.         if (eval(lp,lcook) == FAIL)
  115.             return FAIL;
  116.         freetmps(lp);
  117.         if (eval(rp,rcook) == FAIL)
  118.             return FAIL;
  119.         freetmps(rp);
  120.     } else if (np->g_type == EV_RL) {
  121.         if (eval(rp,rcook) == FAIL)
  122.             return FAIL;
  123.         freetmps(rp);
  124.         if (eval(lp,lcook) == FAIL)
  125.             return FAIL;
  126.         freetmps(lp);
  127.     } else {    /* EV_LRSEP */
  128.         if (eval(lp,lcook) == FAIL)
  129.             return FAIL;
  130.         freetmps(lp);
  131.         free1(NULL, lp);
  132.         if (eval(rp,rcook) == FAIL)
  133.             return FAIL;
  134.         freetmps(rp);
  135.     }
  136.     return b_sube(np, cookflags[cookie]);
  137. }
  138.  
  139. b_sube(np, flags)
  140. register NODEP np;
  141. {
  142.     NODEP lp = np->n_left, rp = np->n_right;
  143.     register int i, r;
  144.     int argsize;
  145.     char buf[40];
  146.     
  147.     if (isassign(np->g_token))
  148.         return as_eval(np);
  149.  
  150.     switch (np->g_token) {
  151.     case '=':
  152.         if (specasn(np, flags) || strasn(np))
  153.             return OKAY;
  154.         inherit(np);
  155.         addcode(np, "\tmove.S\t>A,<A\n");
  156.         return OKAY;
  157.  
  158.     case '(':
  159.         argsize = argmod(rp);
  160.         free1(NULL,rp);
  161.         if (np->g_ty == ET_A) {        /* struct returned */
  162.             frc_ral(AREG);
  163.             indir(np, AREG);
  164.         } else {
  165.             frc_ral(0);
  166.             retreg(np, 0);
  167.         }
  168.         sprintf(buf, "\tjsr\t<A\n\tadd.w\t#%d,sp\n", argsize);
  169.         addcode(np, buf);
  170.         return OKAY;
  171.  
  172.     case ',':
  173.         if (np->g_offs == 0)    /* normal ',' */
  174.             rinherit(np);
  175.         return OKAY;
  176.  
  177.     case DOUBLE '&':
  178.         free1(NULL, rp);
  179.         r = ralloc(0);
  180.         retreg(np, r);
  181.         holdlbls(np);
  182.         np->g_betw = iscc(lp) ? "<FL1\n" :
  183.             "<Q\tbeq\tL1\n";
  184.         addcode(np, iscc(rp) ? ">FL1\n" :
  185.             ">Q\tbeq\tL1\n");
  186.         addcode(np, "\tmoveq\t#1,A\n");
  187.         addcode(np, "\tbra\tL2\nL1:\tclr\tA\nL2:\n");
  188.         return OKAY;
  189.  
  190.     case DOUBLE '|':
  191.         free1(NULL, rp);
  192.         r = ralloc(0);
  193.         retreg(np, r);
  194.         holdlbls(np);
  195.         np->g_betw = iscc(lp) ? "<TL1\n" :
  196.             "<Q\tbne\tL1\n";
  197.         addcode(np, iscc(rp) ? ">TL1\n" :
  198.             ">Q\tbne\tL1\n");
  199.         addcode(np, "\tclr\tA\n");
  200.         addcode(np, "\tbra\tL2\nL1:\tmoveq\t#1,A\nL2:\n");
  201.         return OKAY;
  202.  
  203.     case '?':
  204.         rinherit(np);
  205.         rinhlbls(np);
  206.         np->g_betw = iscc(lp) ? "<FL1\n" : "<Q\tbeq\tL1\n";
  207.         return OKAY;
  208.  
  209.     case ':':
  210.         free1(NULL, rp);
  211.         r = ralloc(0);
  212.         retreg(np, r);
  213.         holdlbls(np);
  214.         np->g_betw = same_a(np, lp) ?
  215.             "\tbra\tL2\nL1:\n"  :
  216.             "\tmove.S\t<A,A\n\tbra\tL2\nL1:\n";
  217.         if (!same_a(np, rp))
  218.             addcode(np, "\tmove.S\t>A,A\n");
  219.         addcode(np, "L2:\n");
  220.         return OKAY;
  221.  
  222.     case '<':
  223.         i = 0;  goto dotst;
  224.     case '>':
  225.         i = 1;  goto dotst;
  226.     case LTEQ:
  227.         i = 2;  goto dotst;
  228.     case GTEQ:
  229.         i = 3;  goto dotst;
  230.     case DOUBLE '=':
  231.         i = 4;  goto dotst;
  232.     case NOTEQ:
  233.         i = 5;
  234. dotst:
  235.         fix_cmp(np, EOPD|EOPA|IOPE|AOPA|AOPD);
  236.         if (flags & CC_OK) {
  237.             np->g_token = (lp->g_ty == ET_U ?
  238.             utstx[i] : tstx[i]) + BR_TOK;
  239.         } else {
  240.             strcpy(np->n_name, lp->g_ty == ET_U ?
  241.             utstnm[i] : tstnm[i]);
  242.             r = ralloc(0);
  243.             retreg(np, r);
  244.             addcode(np, "\tsN\tA\n\tand.w\t#1,A\n");
  245.         }
  246.         return OKAY;
  247.  
  248.     case '*':
  249.         return fixmul(np, bops[0].opflags);
  250.     case '/':
  251.         return fixdiv(np, bops[1].opflags);
  252.     case '%':
  253.         return fixmod(np, bops[2].opflags);
  254.     case '&':    i = 3;  goto doop;
  255.     case '|':    i = 4;  goto doop;
  256.     case '^':    i = 5;    goto doop;
  257.     case '+':
  258.         if (optadd(np, flags, 1))
  259.             return OKAY;
  260.             i = 6;  goto doop;
  261.     case '-':
  262.         if (optadd(np, flags, -1))
  263.             return OKAY;
  264.             i = 7;  goto doop;
  265.     case DOUBLE '<':i = 8;  goto doop;
  266.     case DOUBLE '>':i = 9;
  267. doop:
  268.         strcpy(np->n_name, np->g_ty == ET_U ?
  269.             bops[i].u_op : bops[i].s_op);
  270.         r = fix2ops(np, bops[i].opflags);
  271.         cc_hack(np);
  272.         return r;
  273.     case FIELDAS:
  274.         return fldasn(np, flags);
  275.     default:
  276.         printf("Weird b_eval %s ", np->n_name);
  277.         return FAIL;
  278.     }
  279. }
  280.  
  281. as_eval(np)
  282. register NODEP np;
  283. {
  284.     NODEP rp = np->n_right;
  285.     register int op, i, r;
  286.  
  287.     rp = np->n_right;
  288.  
  289.     op = np->g_token;
  290.     op -= ASSIGN 0;
  291.     switch (op) {
  292.  
  293.     /* these get unfolded now */
  294.     case '*':
  295.             return fixamul(np, bops[0].opflags);
  296.     case '/':
  297.             return fixadiv(np, bops[1].opflags);
  298.     case '%':
  299.             return fixamod(np, bops[2].opflags);
  300.     case '&':    i = 3;  goto doop;
  301.     case '|':    i = 4;  goto doop;
  302.     case '^':    i = 5;    goto doop;
  303.     case '+':    i = 6;  goto doop;
  304.     case '-':    i = 7;  goto doop;
  305.     case DOUBLE '<':i = 8;  goto doop;
  306.     case DOUBLE '>':i = 9;
  307. doop:
  308.         strcpy(np->n_name, np->g_ty == ET_U ?
  309.             bops[i].u_op : bops[i].s_op);
  310.         r = fix_asn(np, bops[i].opflags);
  311.         cc_hack(np);
  312.         return r;
  313.  
  314.     default:
  315.         printf("Weird as_eval %s ", np->n_name);
  316.         return FAIL;
  317.     }
  318. }
  319.  
  320. rinherit(np)
  321. register NODEP np;
  322. {
  323.     register NODEP rp = np->n_right;
  324.  
  325.     np->g_token = rp->g_token;
  326.     np->g_offs = rp->g_offs;
  327.     np->g_rno = rp->g_rno;
  328.     np->g_flags |= RCHILDNM | (rp->g_flags & IMMEDID);
  329. }
  330.  
  331. argmod(np)
  332. register NODEP np;
  333. {
  334.     int size = 0;
  335.  
  336.     if (np->g_token == ',') {
  337.         np->g_type = EV_RL;
  338.         size += argmod(np->n_right);
  339.         size += argmod(np->n_left);
  340.         return size;
  341.     }
  342.     size += onearg(np);
  343.     return size;
  344. }
  345.  
  346. onearg(np)
  347. register NODEP np;
  348. {
  349.     int rv;
  350.  
  351.     /* hack small ICON */
  352.     if (np->g_sz == 1 && np->g_token == ICON)
  353.         np->g_sz = 2;
  354.     /* hack push of 0 */
  355.     if (np->g_token == ICON && np->g_offs == 0 && isimmed(np)) {
  356.         addcode(np, "\tclr.S\t-(sp)\n");
  357.         return (int)np->g_sz;
  358.     }
  359.     /* hack push of #OREG */
  360.     if (np->g_token == OREG && isimmed(np)) {
  361.         np->g_flags &= ~IMMEDID;
  362.         addcode(np, "\tpea\tA\n");
  363.         return 4;
  364.     }
  365.  
  366.     if (np->g_ty == ET_A) {
  367.         rv = strpush(np);
  368.         freetmps(np);
  369.         free1(NULL,np);
  370.         return rv;
  371.     }
  372.  
  373.     switch (np->g_sz) {
  374.     case 1:
  375.         addcode(np, (np->g_ty == ET_U) ?
  376.            "\tclr.w\td0\n\tmove.b\tA,d0\n\tmove.w\td0,-(sp)\n" :
  377.            "\tmove.b\tA,d0\n\text.w\td0\n\tmove.w\td0,-(sp)\n" );
  378.         return 2;
  379.     case 2:
  380.         addcode(np,
  381.            "\tmove.w\tA,-(sp)\n");
  382.         return 2;
  383.     default:
  384.         addcode(np,
  385.            "\tmove.l\tA,-(sp)\n");
  386.         return 4;
  387.     }
  388. }
  389.  
  390. #define MAXD DRV_START
  391. #define MAXA (ARV_START-AREG)
  392. #define NEEDALL    (MAXA*AREG + MAXD)
  393.  
  394. order(np)
  395. register NODEP np;
  396. {
  397.     int l, r;
  398.  
  399.     switch (np->g_type) {
  400.     case E_BIN:
  401.         order(np->n_right);
  402.         r = np->n_right->g_needs;
  403.     case E_UNARY:
  404.         order(np->n_left);
  405.         l = np->n_left->g_needs;
  406.         break;
  407.     default:    /* leaf */
  408.         np->g_type = EV_NONE;
  409.         np->g_needs = 0;
  410.         return;
  411.     }
  412.  
  413.     if (np->g_type == E_UNARY) {
  414.         switch (np->g_token) {
  415.         case STAR:
  416.         case UNARY '&':
  417.             np->g_needs = merge(l,AREG);
  418.             break;
  419.         case '(':
  420.             np->g_needs = NEEDALL;
  421.             break;
  422.         case POSTINC:
  423.         case POSTDEC:
  424.         case '!':
  425.         case TCONV:
  426.             np->g_needs = merge(l,1);
  427.             break;
  428.         case '.':
  429.             if (np->g_fldw) {
  430.                 np->g_needs = merge(l,1);
  431.                 break;
  432.             }
  433.             /* else fall through */
  434.         default:
  435.             np->g_needs = l;
  436.         }
  437.         np->g_type = EV_LEFT;
  438.         return;
  439.     }
  440.  
  441. /* at this point, have binary node */
  442.  
  443.     switch (np->g_token) {
  444.     case DOUBLE '&':
  445.     case DOUBLE '|':
  446.     case '?':
  447.     case ':':
  448.         /* always left-right, no extra regs */
  449.         np->g_type = EV_LRSEP;
  450.         np->g_needs = merge(1, merge(l,r));
  451.         return;
  452.     case ',':
  453.         np->g_needs = merge(l, r);
  454.         np->g_type = EV_LRSEP;
  455.         return;
  456.     case '(':
  457.         np->g_needs = NEEDALL;
  458.         break;
  459.     case '^':
  460.     case DOUBLE '<':
  461.     case DOUBLE '>':
  462.     case ASSIGN '/':
  463.     case ASSIGN DOUBLE '<':
  464.     case ASSIGN DOUBLE '>':
  465.         np->g_needs = merge(bin(l,r), 2);
  466.         break;
  467.     default:
  468.         if (isassign(np->g_token) || np->g_token == '=')
  469.             np->g_needs = merge(rbin(l,r), 1);
  470.         else
  471.             np->g_needs = merge(bin(l,r), 1);
  472.     }
  473.  
  474.     if (isassign(np->g_token) || np->g_token == '=')
  475.         np->g_type = EV_RL;    /* NO PUSHER's on L */
  476.     else
  477.         np->g_type = worst_1st(l, r);
  478.     flag_saves(np, l, r);
  479. }
  480.  
  481. flag_saves(np, l, r)
  482. NODEP np;
  483. {
  484.     NODEP *cpp;
  485.     register int other;
  486.  
  487.     if (np->g_type == EV_LR) {
  488.         cpp = &np->n_left;
  489.         other = r;
  490.     } else {
  491.         cpp = &np->n_right;
  492.         other = l;
  493.     }
  494.     if ((other & 7) >= MAXD || (other/AREG) >= MAXA)
  495.         addtmp(np, cpp);
  496. }
  497.  
  498. addtmp(np, cpp)
  499. NODEP np, *cpp;
  500. {
  501.     NODEP cp, tp;
  502.     NODEP copyone();
  503.  
  504.     cp = *cpp;
  505.     tp = copyone(cp);
  506.     tp->n_left = cp;
  507.     *cpp = tp;
  508.     tp->g_token = PUSHER;
  509.     strcpy(tp->n_name, "pusher");
  510.     tp->g_type = EV_LEFT;
  511. }
  512.     
  513. worst_1st(l,r)
  514. {
  515.     int ld, rd;
  516.  
  517.     ld = l & 7;
  518.     rd = r & 7;
  519.     if (rd > ld)
  520.         return EV_RL;
  521.     if (r > l)
  522.         return EV_RL;
  523.     return EV_LR;
  524. }
  525.  
  526. bin(l,r)
  527. {
  528.     int la, ra, na;
  529.     int ld, rd, nd;
  530.     int rfirst;
  531.  
  532.     la = l/AREG;
  533.     ra = r/AREG;
  534.     ld = l & 7;
  535.     rd = r & 7;
  536.     rfirst = (ra > la) || (rd > ld);
  537.     return rfirst ? rbin(l,r) : rbin(r,l);
  538. }
  539.  
  540. rbin(last,first)
  541. {
  542.     int la, fa, na;
  543.     int ld, fd, nd;
  544.  
  545.     la = last/AREG;
  546.     fa = first/AREG;
  547.     ld = last & 7;
  548.     fd = first & 7;
  549.     na = fa > la ? fa : la + (fa ? 1 : 0);
  550.     if (na > MAXA)
  551.         na = MAXA;
  552.     nd = fd > ld ? fd : ld + (fd ? 1 : 0);
  553.     if (nd > MAXD)
  554.         nd = MAXD;
  555.     return na*AREG + nd;
  556. }
  557.  
  558. merge(need, have)
  559. {
  560.     int na, nd, ha, hd, xa, xd;
  561.  
  562.     na = need/AREG;
  563.     ha = have/AREG;
  564.     nd = need & 7;
  565.     hd = have & 7;
  566.     xa = na > ha ? na : ha;
  567.     xd = nd > hd ? nd : hd;
  568.     return xa*AREG + xd;
  569. }
  570.  
  571. holdlbls(np)
  572. NODEP np;
  573. {
  574.     np->g_bsize = new_lbl();
  575.     new_lbl();
  576. }
  577.  
  578. rinhlbls(np)
  579. NODEP np;
  580. {
  581.     np->g_bsize = np->n_right->g_bsize;
  582. }
  583.  
  584. /* limited version of same address check
  585.     assume one of these is a temp register */
  586. same_a(p1, p2)
  587. NODEP p1, p2;
  588. {
  589.     if (p1->g_token != p2->g_token)
  590.         return 0;
  591.     if (p1->g_rno != p2->g_rno)
  592.         return 0;
  593.     return 1;
  594. }
  595.  
  596. optadd(np, flags, sign)
  597. register NODEP np;
  598. {
  599.     NODEP lp = np->n_left, rp = np->n_right;
  600.  
  601.     if (rp->g_token != ICON)
  602.         return 0;
  603.     if (isimmed(lp) && isimmed(rp)) {
  604.         switch (lp->g_token) {
  605.         case OREG:
  606.         case ONAME:
  607.             inherit(np);
  608.             if (sign == -1)
  609.                 rp->g_offs = -rp->g_offs;
  610.             np->g_offs += rp->g_offs;
  611.  
  612.             if ((flags & IMMA_OK) == 0)
  613.                 imm_oreg(np);
  614.             return 1;
  615.         default:
  616.             return 0;
  617.         }
  618.     }
  619.     return 0;
  620. }
  621.  
  622. iscc(np)
  623. NODEP np;
  624. {
  625.     return (np->g_token >= BR_TOK) || (np->g_flags & SIDE_CC);
  626. }
  627.  
  628. cc_hack(np)
  629. NODEP np;
  630. {
  631.     if (isareg(np))
  632.         return;
  633.     np->g_flags |= SIDE_CC;
  634. }
  635.  
  636. cctok(np)
  637. NODEP np;
  638. {
  639.     if (np->g_token >= BR_TOK)
  640.         return np->g_token - BR_TOK;
  641.     if (np->g_flags & SIDE_CC)
  642.         return B_NE;
  643.     printf("cctok error ");
  644.     return 0;
  645. }
  646.